package failover;

import java.io.BufferedWriter;
import java.io.Console;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import network.KrakenClient;
import network.messages.KrakenClientMsg;
import network.messages.KrakenServerMsg;
import network.ssl.KrakenSSLClient;

import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import enumTypes.Rank;

import tools.ExecuteExternalApplication;
import tools.FileUtils;
import tools.PasswordSecurity;
import tools.StringUtils;

import bdd.sql.server.bean.ServerAuth;
import bdd.sql.server.bean.ServerCentral;
import bdd.sql.server.bean.ServerSite;
import bdd.sql.server.bean.ServerStorage;
import bdd.sql.server.bean.User;
import bdd.sql.server.hibernate.HibernateUtil;

public class Deployment {

	/*
	 * Demander les logins de l'utilisateur.
	 * Se connecter à la base
	 * Demander le rôle du serveur, Enum/liste prédifinie?
	 * Télécharger le tar correspondant.
	 * Dezipper le tar. (inclut la conf réseau?)
	 * Restart networking
	 * Enregistrer le service kraken.
	 * 
	 * Si besoin d'une ihm, télécharger kde.
	 */
	
	public Deployment() {
		System.setSecurityManager(null);
		System.out.println("successfully updated security manager!");
		
		System.out.print("Input username : ");
		Scanner sc = new Scanner(System.in);
		String username = sc.nextLine();
		
		Console cnsl = System.console();
		String password = new String(cnsl.readPassword("Input password: "));
		
		Session session = HibernateUtil.getSession();
		
		@SuppressWarnings("unchecked")
		List<User> resultats = session.createCriteria(User.class).add(Restrictions.eq("user_mail", username)).list();
		
		if(resultats.size() == 0) {
			System.err.println("Invalid credentials.");
			session.close();
			System.exit(1);
		}
		
		for(int i = 0; i<resultats.size(); i++) {
			User u = resultats.get(i);
			
			byte[] hash = PasswordSecurity.sha256_2(password, u.getUser_seedPwd());
			String b64 = StringUtils.toBase64(hash);
			
			if(u.getUser_pwd().equals(b64) && u.getUser_rank().equals(Rank.Administrateur))
				System.out.println("User logged in successfully!");
			else {
				System.err.println("Invalid credentials.");
				session.close();
				System.exit(1);
			}
		}

		// lister les serveurs en base
		int i = 0;
		System.out.println("Retriving sever list...");
		// TODO ajouter un nouveau serveur?
		
		List<ServerAuth> list_1 = session.createCriteria(ServerAuth.class).list();
		for(ServerAuth s : list_1) {
			System.out.println("["+i+"]"+"\t"+s+"\t"+s.getAuth_ip_adress());
			i++;
		}
		
		List<ServerCentral> list_2 = session.createCriteria(ServerCentral.class).list();
		for(ServerCentral s : list_2) {
			System.out.println("["+i+"]"+"\t"+s+"\t"+s.getServCentr_ip());
			i++;
		}
		
		List<ServerSite> list_3 = session.createCriteria(ServerSite.class).list();
		for(ServerSite s : list_3) {
			System.out.println("["+i+"]"+"\t"+s+"\t"+s.getSiteserv_ip());
			i++;
		}
		
		List<ServerStorage> list_4 = session.createCriteria(ServerStorage.class).list();
		for(ServerStorage s : list_4) {
			System.out.println("["+i+"]"+"\t"+s+"\t"+s.getStorserv_ip());
			i++;
		}

		System.out.print("Server to replace: ");
		sc = new Scanner(System.in);
		int server = sc.nextInt();
		
		// télécharger les données
		i = 0;
		String ip = null;
		String ip_central = null;
		String name = null;
		String archive = "";
		for(ServerAuth s : list_1) {
			if(i == server) {
				archive = s.getConf().getConf_path();
				//System.out.println("Downloading archive "+archive);
				//FileUtils.byteArrayToFile(s.getConf().getConf_data(), archive);
				ip = s.getAuth_ip_adress();
				name = s.toString();
				break;
			}
			i++;
		}
		
		if(ip == null) {
			for(ServerCentral s : list_2) {
				ip_central = s.getServCentr_ip();
				if(i == server) {
					archive = s.getConf().getConf_path();
					//System.out.println("Downloading archive "+archive);
					//FileUtils.byteArrayToFile(s.getConf().getConf_data(), archive);
					ip = s.getServCentr_ip();
					name = s.toString();
					break;
				}
				i++;
			}
		}

		if(ip == null) {
			for(ServerSite s : list_3) {
				if(i == server) {
					archive = s.getConf().getConf_path();
					//System.out.println("Downloading archive "+archive);
					//FileUtils.byteArrayToFile(s.getConf().getConf_data(), archive);
					ip = s.getSiteserv_ip();
					name = s.toString();
					break;
				}
				i++;
			}
		}

		if(ip == null) {
			for(ServerStorage s : list_4) {
				if(i == server) {
					archive = s.getConf().getConf_path();
					//System.out.println("Downloading archive "+archive);
					//FileUtils.byteArrayToFile(s.getConf().getConf_data(), archive);
					ip = s.getStorserv_ip();
					name = s.toString();
					break;
				}
				i++;
			}
		}

		// confirmation
		sc = new Scanner(System.in);
		String replace = "";
		do {
			System.out.println("Replace "+name+" ["+ip+"] ? (y|n)");
			replace = sc.nextLine();
			if(replace.equals("n")) {
				System.out.println("Nothing done, exiting!");
				System.exit(0);
			}
		} while(!replace.equals("y"));
		
		// demande de téléchargement
		System.out.println("Downloading archive "+archive);
		ArrayList<String> msg_list = new ArrayList<String>();
		msg_list.add(KrakenClientMsg.KRAKEN_CLIENT.makeCommand());
		msg_list.add(KrakenClientMsg.ASK_FOR_CONFIGURATION.makeCommand(" "+archive, " "+archive));
		msg_list.add(KrakenClientMsg.END_CLIENT.makeCommand());
		
		KrakenSSLClient dl_client = new KrakenSSLClient(msg_list, ip_central, 0);
		dl_client.connect();
		dl_client.communicate();

		String answer = dl_client.getFinalAnswer();
		if(!answer.equalsIgnoreCase(KrakenServerMsg.END_SERVER.toString())) {
			System.out.println("Fin annormale du serveur: "+answer);
			System.exit(1);
		}
		
		int exit = 0;
		try {
			//ExecuteExternalApplication.executeShell("sudo", "su", "|", "echo", "\"test\"");
			
			// archive
			System.out.println("tar -zxvf "+archive);
			exit = ExecuteExternalApplication.executeShell("tar", "-zxvf", archive, "-C", "/");
			System.out.println("tar result "+exit);
			
			// TODO hostname
			
			// network
			System.out.println("Reconfiguring network...");
			String interfaces = "/etc/network/interfaces";
			exit = ExecuteExternalApplication.executeShell("rm", interfaces);
			System.out.println("rm old network config result "+exit);
			
			File network_config = new File(interfaces);
			if (!network_config.exists())
				network_config.createNewFile();
			
			FileWriter fw = new FileWriter(network_config.getAbsoluteFile());
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write("auto lo\n");
			bw.write("iface lo inet loopback\n");
			bw.write("\n");
			bw.write("auto eth0\n");
			bw.write("iface eth0 inet static\n");
			bw.write("\taddress "+ip+"\n");
			bw.write("\tnetmask 255.255.255.0\n");
			
			String[] gateway = ip.split("\\.");
			gateway[3] = "254";
			bw.write("\tgateway "
					+ gateway[0] + "."
					+ gateway[1] + "."
					+ gateway[2] + "."
					+ gateway[3] + "\n");
			bw.write("\tdns-nameservers 172.19.1.246 172.19.1.17\n");
			bw.close();
			
			//ExecuteExternalApplication.executeShell("ifdown", "eth0");
			//ExecuteExternalApplication.executeShell("ifup", "eth0");
			
			// service
			exit = ExecuteExternalApplication.executeShell("update-rc.d", "kraken", "defaults");
			System.out.println("service update result "+exit);
			
			//ExecuteExternalApplication.executeShell("reboot");
		} catch (IOException | InterruptedException e) {
			e.printStackTrace();
		}
	}
	

	public static void main(String[] args) throws IOException {
		Deployment d = new Deployment();
	}
}
